gusucode.com > 阵列信号处理书的源码 > MATALB 程序/6.角度和时延联合估计(JADE)算法MATLAB程序/jade.m

    function [theta,tau] = jade(H,g,r,P,m1,m2);


    [M,PL] = size(H);
    if length(g) < PL, g = [g zeros(1,PL-length(g))]; end	% zero pad
    if length(g) > PL, 
	H = [H zeros(M,length(g)-PL)]; 		% zero pad
	[M,PL] = size(H);
    end	% zero pad

    if nargin < 4, P=1; end
    if nargin < 5, m1=1; end
    if nargin < 6, m2=1; end

    L = PL/P;		% impulse response length measured in ``symbol periods''

    if m1*M <= r, error('m1 is not large enough to separate all sources'); end


% STEP 1: FFT OF ROWS OF G TO GET VANDERMONDE STRUCTURE ON THE ROWS

    G = fft(g);
    H1 = fft(H.').';

% assume bandlimited signals: truncate out-of-band part
% because G is very small there
    if ( floor(L/2)*2 == L ),
	% L even
	G = G([PL-L/2+1:PL 1:L/2]);
	H1 = H1(:,[PL-L/2+1:PL 1:L/2]);
    else
	% L odd
	L2 = floor(L/2);
	G = G([PL-L2+1:PL 1:L2+1]);
	H1 = H1(:,[PL-L2+1:PL 1:L2+1]);
    end

% divide out the known signal waveform
% (assume it is nonsing! else work on intervals)
    for i = 1:M,
	rat(i,:) = H1(i,:) ./ G;
    end

% STEP 2: FORM HANKEL MATRIX OF DATA, WITH m1 FREQ SHIFTS AND m2 SPATIAL SHIFTS

    [m_rat,n_rat] = size(rat);

    % sanity checks
    if m1 >= n_rat, n_rat, error('m1 too large to form so many shifts'); end
    if m2 >= m_rat, m_rat, error('m2 too large to form so many shifts'); end
    if ((r > (m1-1)*(M-m2+1)) | (r > m1*(M-m2)) | (r > 2*m2*(n_rat-m1+1))), 
	error('m1 too large to form so many shifts and still detect r paths'); 
    end

    % spatial shifts
    X0 = [];
    for i=1:m2;
       X0 = [X0 rat(i:M-m2+i,:)];
    end
    M = M-m2+1;		% number of antennas is reduced by the shifting process

    % freq shifts
    X = [];
    Xt = [];
    for i=1:m1;
       Xshift = [];
       for j=1:m2;
	   Xshift = [Xshift X0(:,(j-1)*n_rat+i:j*n_rat-m1+i)];
       end
       Xt = [Xt; Xshift];
   end
    % size Xt: m1(M-m2+1) * (m2-1)(n_rat-m1+1)
    Rat = Xt;

% STEP 3: TRANSFORM TO REAL; DOUBLE NUMBER OF OBSERVATIONS
% same tricks as in `unitary esprit'

    Q2m = qtrans(m1);
    Im = eye(m1,m1);
    Jm = Im(m1:-1:1,:);
    Q2M = qtrans(M);
    IM = eye(M,M);
    JM = IM(M:-1:1,:);
    Q2M = qtrans(M);

    Q2 = kron(Q2m,Q2M);
    J = kron(Jm,JM);

    [mR,NR] = size(Rat);
    Ratreal = [];
    for i=1:NR,
	z1 = Rat(:,i);		% kron(a1,a2)
	z2 = J*conj(z1);	% kron(J a1,J a2)
	Z = real(Q2' * [z1 z2] * [1 sqrt(-1); 1 -sqrt(-1)] ); 

	Ratreal = [Ratreal Z];
    end

    Rat = Ratreal;
    [mR,NR] = size(Rat);



% STEP 4: SELECT (should be ESTIMATE?) NUMBER OF MULTIPATHS FROM Rat

    [u,s,v] = svd(Rat);		% only need u: use subspace tracking...
    u = u(:,1:r);
    v = v(:,1:r);

% r should be set at a gap in the singular values


% STEP 5: FORM SHIFTS OF THE DATA MATRICES
% AND REDUCE RANKS OF DATA MATRICES

    [mM,PL1] = size(Rat);

% selection and transform matrices:
    Jxm = [eye(m1-1,m1-1)  zeros(m1-1,1)];
    Jym = [zeros(m1-1,1) eye(m1-1,m1-1) ];
    JxM = [eye(M-1,M-1)  zeros(M-1,1)];
    JyM = [zeros(M-1,1) eye(M-1,M-1) ];

    Q1m = qtrans(m1-1);
    Q1M = qtrans(M-1);

    Kxm = real( kron(Q1m',IM) * kron(Jxm+Jym,IM) * kron(Q2m,IM) );
    Kym = real( kron(Q1m',IM) * sqrt(-1)*kron(Jxm-Jym,IM) * kron(Q2m,IM) );

    KxM = real( kron(Im,Q1M') * kron(Im,JxM+JyM) * kron(Im,Q2M) );
    KyM = real( kron(Im,Q1M') * sqrt(-1)*kron(Im,JxM-JyM) * kron(Im,Q2M) );

% For estimating DOA:
    Ex1 = KxM*u;
    Ey1 = KyM*u;
    % size: m(M-1) by r

% For estimating tau:
    % select first/last m1-1 blocks (each of M rows)
    Ex2 = Kxm*u;
    Ey2 = Kym*u;
    % size: (M-1)m1 by r


% sanity checks:
    % X1, X2, Y1, Y2 should be taller and wider than r
    if size(Ex1,1) < r, error('Ex1 not tall enough'); end
    if size(Ex2,1) < r, error('Ex2 not tall enough'); end

% reduce to r columns
    [Q,R] = qr([Ex1,Ey1]);
    Ex1 = R(1:r,1:r);
    Ey1 = R(1:r,r+1:2*r);

    [Q,R] = qr([Ex2,Ey2]);
    Ex2 = R(1:r,1:r);
    Ey2 = R(1:r,r+1:2*r);



% STEP 6: DO JOINT DIAGONALIZATION on Ex2\Ey2 and Ex1\Ey1

% 2-D Mathews-Zoltowski-Haardt method.  There are at least 4 other methods, but
% the differences are usually small.  This one is easiest with standard matlab

    A = Ex2\Ey2 + sqrt(-1)*Ex1\Ey1;
    [V,Lambda] = eig(A);
    Phi = real( Lambda );
    Theta = -imag( Lambda );

% STEP 7: COMPUTE THE DELAYS AND ANGLES
    Phi = diag(Phi);
    Theta = diag(Theta);
    
    tau = -2*atan(real(Phi))/(2*pi)*L;
    sintheta = 2*atan(real(Theta));

    theta = asin(sintheta/pi);
    theta = theta*180/pi;			% DOA in degrees